/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Data.Enemigo;

import Data.Token;
import Principal.Ataque;
import Principal.Casilla;
import Principal.Coordenada;
import Principal.Efectos;
import Principal.Sonidos;
import Principal.Tablero;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author REI
 */
public class Ejecucion implements Runnable{
    
    private HashMap<Integer,NodoEnemigo> enemigos;
    private HashMap<Integer,NodoArma> armas;
    private HashMap<Integer,NodoImagen> imagenes;
    private HashMap<Integer,NodoPotencia> potencias;
    private HashMap<Integer, NodoEstrategia> estrategias;
    private ArrayList<NodoEnemigoArma> armas_enemigos;
    private ArrayList<Enemigo> lstenemigos;
    private TablaSimbolos tabla;
    private ArrayList<Object> instrucciones;
    private Validaciones validar;
    private boolean detener = false;
    private Casilla[][] casillas;
    private int jugx;
    private int jugy;
    private int id;
    Sonidos sonido = new Sonidos();
    
    
    volatile Tablero tablero;
    
    public Thread hilo;

    public Ejecucion(Tablero tab, ManejoEnemigo man) {
        
        iniciarDatos(man);
        this.tablero = tab;
        hilo = new Thread(this);
        
        
    }
    
    private void iniciarDatos(ManejoEnemigo man)
    {
        this.enemigos = man.getEnemigos();
        this.armas = man.getArmas();
        this.imagenes = man.getImagenes();
        this.potencias = man.getPotencias();
        this.estrategias = man.getEstrategias();
        this.armas_enemigos = new ArrayList<NodoEnemigoArma>();
        this.lstenemigos = man.getLstenemigos();
        this.validar = new Validaciones();
        
        this.tabla = man.getTabla();
        this.casillas = man.getCasillas();
        this.id = man.getId();
        this.setInstrucciones(man.getInstrucciones());
        
    }
    
    public void Iniciar()
    {
        hilo.start();
    }

    
    public void setTabla(TablaSimbolos tabla) {
        this.tabla = tabla;
    }    

    public void setLstenemigos(ArrayList<Enemigo> lstenemigos) {
        this.lstenemigos = lstenemigos;
    }
       

    public void setInstrucciones(ArrayList<Object> instrucciones) {
        this.instrucciones = instrucciones;
    }
        

    public void setCasillas(Casilla[][] casillas) {
        this.casillas = casillas;
    }
   

    public void setJug(int jugx, int jugy) {
        this.jugx = jugx;
        this.jugy = jugy;
    }
        
    public void setId(int id)
    {
        this.id = id;
    }    
   

   public boolean existePotencia(int id)
    {
        return potencias.containsKey(id);
    }

    public boolean existeArma(int id)
    {
        return armas.containsKey(id);
    }

    public boolean existeEnemigo(int id)
    {
        return enemigos.containsKey(id);
    }
    public boolean existeEstrategia(int id)
    {
        return estrategias.containsKey(id);
    }
    public boolean existeImagen(int id)
    {
        return imagenes.containsKey(id);
    }

    public NodoPotencia buscarPotencia(int id)
    {
        return potencias.get(id);
    }

    public NodoArma buscarArma(int id)
    {
        return armas.get(id);
    }

    public NodoEnemigo buscarEnemigo(int id)
    {
        return enemigos.get(id);
    }
    public Enemigo buscarEnemigo2(int ide)
    {
        Enemigo encontrado = null;
        for (Enemigo enemy : lstenemigos) {
            
            if(enemy.getId()== ide && id == enemy.getArchivo())
            {
                return enemy;
            }
        }
        return encontrado;
    }
    
    public NodoEstrategia buscarEstrategia(int id)
    {
        return estrategias.get(id);
    }
    public NodoImagen buscarImagen(int id)
    {
        return imagenes.get(id);
    }
    
    public NodoEnemigoArma buscarArmaEnemigo(int idenemigo, int idarma)
    {
        NodoEnemigoArma encontrado = null;
        
        for (NodoEnemigoArma nodoEnemigoArma : armas_enemigos) {
            
            if(nodoEnemigoArma.getArma()==idarma && nodoEnemigoArma.getEnemigo() == idenemigo)
            {
                return nodoEnemigoArma;
            }
        }
        
        return encontrado;
    }
    
    public NodoEnemigoArma buscarArmaEnemigo(int idenemigo)
    {
        NodoEnemigoArma encontrado = null;
        
        for (NodoEnemigoArma nodoEnemigoArma : armas_enemigos) {
            
            if(nodoEnemigoArma.getEnemigo() == idenemigo)
            {
                return nodoEnemigoArma;
            }
        }
        
        return encontrado;
    }
    
    private int buscarMuncionesEnemigo(int enemy)
    {
        int total =0;
        
        Enemigo enemigo = buscarEnemigo2(enemy);
        
        if(enemigo!=null)
        {
            if(enemigo.getArma()!=null)
            {
                NodoArma arma = enemigo.getArma();
            
                total = total + arma.getMuniciones();
                return total;
            }
            
        }
                
        
        return total;
    }
    
    private void addArmaEnemigo(int enemy, int arma)
    {
        boolean existe = false;
        
        for (NodoEnemigoArma nodoEnemigoArma : armas_enemigos) {
            
            if(nodoEnemigoArma.getEnemigo() == enemy && nodoEnemigoArma.getArma() == arma)
            {
                existe = true;
                break;
            }
        }
        
        if(!existe)
        {
            armas_enemigos.add(new NodoEnemigoArma(enemy, arma));
            Enemigo enemigo = buscarEnemigo2(enemy);
            
            if(buscarArma(arma)!=null && enemigo!=null)
            {
                enemigo.setArma(buscarArma(arma));
            }
            
        }
    }
        
    public void EjecutarEstrategia()
    {
        while(tablero.isJugando())
        {
            EjecutarInstrucciones(instrucciones);
            try {
                Thread.sleep(400);
            } catch (InterruptedException ex) {
                Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    private void EjecutarInstrucciones(ArrayList<Object> instrucciones)
    {
        NodoArbol instruccion;
        int instru;
        
        for (Object object : instrucciones) {
            
            instruccion = (NodoArbol)object;
            instru = instruccion.getEtiqueta();
            switch(instru)
            {
                case Instruccion.SETF:                
                    ejecutarSetf(instruccion.getHojas().get(0),instruccion.getHojas().get(1));
                    break;                
                case Instruccion.ASIGARMA:                   
                    asignarArma(instruccion.getHojas().get(0),instruccion.getHojas().get(1));
                    break;                
                case Instruccion.SENTWHILE:
                    analizarWhile(instruccion.getHojas());
                    break;
                case Instruccion.SENTIF:
                    analizarIf(instruccion.getHojas());
                    break;
                case Instruccion.SENTFOR:
                    analizarFor(instruccion.getHojas());
                    break;
                case Instruccion.DETENER:
                    detener = true;
                    return;
                case Instruccion.PAUSAR:
                    pausar(instruccion.getHojas().get(0));
                    break;
                case Instruccion.GIRAR:
                    girar(instruccion.getHojas().get(0), instruccion.getHojas().get(1), instruccion.getHojas().get(2));
                    break;
                case Instruccion.AVANZAR:
                    avanzar(instruccion.getHojas().get(0), instruccion.getHojas().get(1), instruccion.getHojas().get(2));
                    break;
                case Instruccion.ASIGPASO:
                    asignarPaso(instruccion.getHojas().get(0), instruccion.getHojas().get(1), instruccion.getHojas().get(2),instruccion.getHojas().get(3), instruccion.getHojas().get(4));
                    break;
                case Instruccion.ASIGSALTO:
                    asignarSalto(instruccion.getHojas().get(0), instruccion.getHojas().get(1), instruccion.getHojas().get(2),instruccion.getHojas().get(3));
                    break;
                case Instruccion.ASIGHABIL:
                    asignarHabilidad(instruccion.getHojas().get(0), instruccion.getHojas().get(1), instruccion.getHojas().get(2),instruccion.getHojas().get(3));
                    break;
                case Instruccion.ACTPUNTEO:
                    tablero.HUD = 1;
                    break;
                case Instruccion.ACTVIDAS:
                    tablero.HUD = 0;
                    break;
                case Instruccion.ACTTIEMPO:
                    tablero.HUD = 0;
                    break;
                case Instruccion.ACTARMA:
                    tablero.HUD = 2;
                    break;
                case Instruccion.ACTMUNI:
                    tablero.HUD = 0;
                    break;
                    
            }

            if(detener)
            {
                break;
            }
            
            
            
        }

        
    }

    private void ejecutarSetf(Object id, Object val) {
        
        Simbolo variable; 
        Token nomvar;
        NodoArbol valor = evaluarExp((NodoArbol)val);
        
        if(valor!=null)
        {
            nomvar = (Token)id;
            variable = tabla.buscarSimbolo(nomvar.getLexema());
            int tipoval = (Integer)valor.getHojas().get(1);
            if(variable!=null)
            {
                
                int casteo = validar.castear(variable.tipo, tipoval);
                if(casteo!= -1 )
                {
                    variable.setValor(valor.getHojas().get(0));
                }
                
                
            }
        }
        
        
        
    }

    private void asignarArma(Object enemy, Object weapon) {
        
        NodoArbol enemigo = (NodoArbol)enemy;
        NodoArbol arma = (NodoArbol)weapon;
        
        NodoArbol idenemigo = evaluarExp(enemigo);
        NodoArbol idarma = evaluarExp(arma);
        int tipoenemigo = Integer.parseInt(idenemigo.getHojas().get(1).toString());
        int tipoarma = Integer.parseInt(idarma.getHojas().get(1).toString());
        
        if(tipoenemigo == Tipo.ENTERO && tipoarma == Tipo.ENTERO)
        {
            int valorenemigo = Integer.parseInt(idenemigo.getHojas().get(0).toString());
            int valorarma = Integer.parseInt(idarma.getHojas().get(0).toString());
            
            if(existeEnemigo(valorenemigo) && existeArma(valorarma))
            {
               addArmaEnemigo(valorenemigo, valorarma);
            }
        }
        
        
        
    }
    
    private void avanzar(Object exp1, Object exp2, Object exp3)
    {
        NodoArbol strategy = evaluarExp((NodoArbol)exp1);
        NodoArbol enemy = evaluarExp((NodoArbol)exp2);
        NodoArbol steps = evaluarExp((NodoArbol)exp3);        
        
        int idestrategia = Integer.parseInt(strategy.getHojas().get(0).toString());
        int idenemigo = Integer.parseInt(enemy.getHojas().get(0).toString());
        int pasos = Integer.parseInt(steps.getHojas().get(0).toString());
        
        if(existeEstrategia(idestrategia))
        {
            NodoEstrategia estrategia = buscarEstrategia(idestrategia);
            Enemigo enemigo = buscarEnemigo2(idenemigo);
            
            if(enemigo!=null)
            {
                enemigo.setEstrategia(estrategia);
                ejecutarAvanzar(enemigo, estrategia, pasos, 3);
            }
        }
    }
    
    
    private void asignarPaso(Object exp1, Object exp2, Object exp3, Object exp4, Object exp5)
    {
        NodoArbol estrategia = evaluarExp((NodoArbol)exp1);
        NodoArbol enemigo = evaluarExp((NodoArbol)exp2);
        NodoArbol posx = evaluarExp((NodoArbol)exp3);
        NodoArbol posy = evaluarExp((NodoArbol)exp4);
        
        
        int idestrategia = Integer.parseInt(estrategia.getHojas().get(0).toString());
        int idenemigo = Integer.parseInt(enemigo.getHojas().get(0).toString());
        int px = Integer.parseInt(posx.getHojas().get(0).toString());
        int py = Integer.parseInt(posy.getHojas().get(0).toString());
        int mov = Integer.parseInt(exp5.toString());
        
        if(existeEstrategia(idestrategia))
        {
            NodoEstrategia estrategi = buscarEstrategia(idestrategia);
            Enemigo enemi = buscarEnemigo2(idenemigo);
            
            if(enemi!= null)
            {
                enemi.setEstrategia(estrategi);
                ejecutarPaso(enemi, estrategi, px, py, mov);
            }
                    
        }
    }
    
    private void asignarSalto(Object exp1, Object exp2, Object exp3, Object exp4)
    {
        NodoArbol estrategia = evaluarExp((NodoArbol)exp1);
        NodoArbol enemigo = evaluarExp((NodoArbol)exp2);
        NodoArbol posx = evaluarExp((NodoArbol)exp3);
        NodoArbol posy = evaluarExp((NodoArbol)exp4);
       
        
        int idestrategia = Integer.parseInt(estrategia.getHojas().get(0).toString());
        int idenemigo = Integer.parseInt(enemigo.getHojas().get(0).toString());
        int px = Integer.parseInt(posx.getHojas().get(0).toString());
        int py = Integer.parseInt(posy.getHojas().get(0).toString());
        
        if(existeEstrategia(idestrategia))
        {
            NodoEstrategia estrategi = buscarEstrategia(idestrategia);
            Enemigo enemi = buscarEnemigo2(idenemigo);
            
            if(enemi!= null)
            {
                enemi.setEstrategia(estrategi);                
                ejecutarSalto(enemi, estrategi, px, py);
            }
                    
        }
        
        
    }
    
    private void asignarHabilidad(Object exp1, Object exp2, Object exp3, Object exp4)
    {
        NodoArbol estrategia = evaluarExp((NodoArbol)exp1);
        NodoArbol enemigo = evaluarExp((NodoArbol)exp2);
        NodoArbol arma = evaluarExp((NodoArbol)exp3);
        NodoArbol detonaciones = evaluarExp((NodoArbol)exp4);
       
        
        int idestrategia = Integer.parseInt(estrategia.getHojas().get(0).toString());
        int idenemigo = Integer.parseInt(enemigo.getHojas().get(0).toString());
        int idarma = Integer.parseInt(arma.getHojas().get(0).toString());
        int nodeto = Integer.parseInt(detonaciones.getHojas().get(0).toString());
        
        if(existeEstrategia(idestrategia))//verificamos que exista la estrategia
        {
            NodoEstrategia estrategi = buscarEstrategia(idestrategia);
            Enemigo enemi = buscarEnemigo2(idenemigo);
            
            if(enemi!= null)//verificamos que exista el enemigo
            {
                if(existeArma(idarma))//verificamos que exista el arma
                {
                    NodoEnemigoArma armaasig= buscarArmaEnemigo(idenemigo, idarma);
                    
                    if(armaasig != null)//verificamos que este asignada al enemigo
                    {
                        NodoArma weapon = buscarArma(idarma);
                        
                        if(weapon.puedeDisparar(nodeto)) //verifica que pueda disparar
                        {
                            if(nodeto > weapon.getMuniciones())
                            {
                                int disparos = weapon.getMuniciones();
                                weapon.balasDisparadas(disparos);
                                enemi.setArma(weapon);
                                enemi.setEstrategia(estrategi);
                                enemi.atacar(estrategi, disparos);
                                disparar(enemi);
                            }
                            else
                            {                                
                                weapon.balasDisparadas(nodeto);
                                enemi.setArma(weapon);
                                enemi.setEstrategia(estrategi);
                                sonido.efecto(Efectos.ESHOT);
                                enemi.atacar(estrategi, nodeto);
                                disparar(enemi);
                            }
                        }
                        
                    }
                }
            }
                    
        }
        
        
    }
    
    private void ejecutarPaso(Enemigo enemigo, NodoEstrategia estrategia, int x, int y,int mov)
    {
        Coordenada coordenada;
        int dir;
        
        if(mov == Instruccion.LINEAL)
        {
            if(x > enemigo.getCol())
            {
                dir = 2;
                coordenada = new Coordenada(enemigo, x, enemigo.getFil(), dir, estrategia);
                MoverEnemigos(coordenada);
            }
            else
            {
                dir = 4;
                coordenada = new Coordenada(enemigo, x, enemigo.getFil(), dir, estrategia);
                MoverEnemigos(coordenada);
            }
            
            if(y > enemigo.getFil())
            {
                dir = 3;
                coordenada = new Coordenada(enemigo, enemigo.getCol(), y, dir, estrategia);
                MoverEnemigos(coordenada);
            }
            else
            {
                dir = 1;
                coordenada = new Coordenada(enemigo, enemigo.getCol(), y, dir, estrategia);
                MoverEnemigos(coordenada);
                
            }
        }
        else if(mov == Instruccion.CIRCULAR)
        {
            int dirx;
            int diry;
            int pasos =0;
            int c;
            int f;
            int pc;
            int pf;


            if(x > enemigo.getCol())
            {
                dirx = 2;
                pasos = pasos + x - enemigo.getCol();
                c = 1;
            }
            else
            {
                dirx = 4;
                pasos = pasos + enemigo.getCol()-x;
                c = -1;
            }

            if(y >  enemigo.getFil())
            {
                diry = 3;
                pasos = pasos + y - enemigo.getFil();
                f = 1;
            }
            else
            {
                diry = 1;
                pasos = pasos + enemigo.getFil()-y;
                f = -1;
            }

            for(int i=0; i < pasos; i++)
            {
                if(i%2==0)
                {
                    pc = enemigo.getCol()+c;
                    
                        coordenada = new Coordenada(enemigo,pc , enemigo.getFil(), dirx, estrategia);
                        MoverEnemigos(coordenada);
                    
                    
                }
                else
                {
                    pf = enemigo.getFil()+f;
                    
                    
                        coordenada = new Coordenada(enemigo, enemigo.getCol(),pf , diry, estrategia);
                        MoverEnemigos(coordenada);
                    
                    
                }
            }


        }

        
        
        
    }
    
    private void ejecutarSalto(Enemigo enemigo, NodoEstrategia estrategia, int x, int y)
    {
        Coordenada coordenada;
        int dir = enemigo.getDir();
        int w = tablero.getNivel().getAncho();
        int h = tablero.getNivel().getAlto();
        
        
        if( (x >= 0 && x < w - 1) && (y >= 0 && y < h-1 ) )
        {
        
            if(casillas[y][x].getEspacio().isPasable())
            {
                
                 if(x == jugx && y == jugy)
                 {
                     estrategia.actualizarpunteo(1);
                 }
                 else
                 {
                     estrategia.actualizarpunteo(1);
                 }
                 tablero.sonido.efecto(Efectos.JUMP); 

                 int xf = casillas[y][x].getX() + (casillas[y][x].getAncho() / 2 - enemigo.getAncho() / 2);
                 int yf = casillas[y][x].getY() + (casillas[y][x].getAlto() / 2 - enemigo.getAlto() / 2);
                 enemigo.setX(xf);
                 enemigo.setY(yf);
                 enemigo.setCol(x);
                 enemigo.setFil(y);

                 if(x > enemigo.getCol())
                 {
                     dir = 2;
                 }
                 else
                 {
                     dir = 4;
                 }
                 coordenada = new Coordenada(enemigo, x,y,dir, estrategia);
                 MoverEnemigos(coordenada);


            }
            else
            {
                estrategia.actualizarpunteo(-2);
            }
            
        
        } 
        else
        {
            estrategia.actualizarpunteo(-2);
        }
            
        
        
    }
    
    private void ejecutarAvanzar(Enemigo enemigo, NodoEstrategia estrategia, int pasos,int op)
    {
        int dire = enemigo.getDir();
        Coordenada coordenada;
        switch(dire)
        {
            case 1://arriba
            {
                int posf = enemigo.getFil() - pasos; 
                
                if(posf<0)
                {
                    posf =0;
                }
                coordenada = new Coordenada(enemigo,enemigo.getCol(),posf, dire, estrategia);
                MoverEnemigos(coordenada);
//                movimientos.add(coordenada);
                break;
            }
            case 2://derecha
            {
                int posf = enemigo.getCol() + pasos;
                coordenada = new Coordenada(enemigo,posf,enemigo.getFil(), dire, estrategia);
                MoverEnemigos(coordenada);
//                movimientos.add(coordenada);
                break;
            }
            case 3://abajo
            {
                int posf = enemigo.getFil() + pasos;
                coordenada = new Coordenada(enemigo,enemigo.getCol(),posf, dire, estrategia);
                MoverEnemigos(coordenada);
//                movimientos.add(coordenada);
                break;
            }
            case 4://izquierda
            {
                int posc = enemigo.getCol() - pasos;
                if(posc<0)
                {
                    posc =0;
                }
                int posf = enemigo.getFil();
                coordenada = new Coordenada(enemigo,posc,posf, dire, estrategia);
                MoverEnemigos(coordenada);
//                movimientos.add(coordenada);

                break;
            }
        }

        
    }
    
    private void girar(Object estrategia, Object enemigo, Object orientacion)
    {
        NodoArbol estrategy = evaluarExp((NodoArbol)estrategia);
        NodoArbol enemy = evaluarExp((NodoArbol)enemigo);
        NodoArbol orientation = evaluarExp((NodoArbol)orientacion);
        
        int valestrategia = Integer.parseInt(estrategy.getHojas().get(0).toString());
        int valenemy = Integer.parseInt(enemy.getHojas().get(0).toString());
        int valorientation = Integer.parseInt(orientation.getHojas().get(0).toString());
        
        if(existeEstrategia(valestrategia))
        {
                 
            Enemigo enemi =buscarEnemigo2(valenemy);
            try
            {
            enemi.setEstrategia(buscarEstrategia(valestrategia));
            if(enemi!=null)
            {
                int nuevadir = enemi.getDir()+ valorientation;

                if(nuevadir > 4)
                {
                    enemi.setDir(1);
                    Thread.sleep(200);
                }
                else if(nuevadir < 1)
                {
                    enemi.setDir(4);
                    Thread.sleep(200);
                }
                else
                {
                    enemi.setDir(nuevadir);
                    Thread.sleep(200);
                }
                
            }
            
            
            }catch (InterruptedException ex) {
            Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
        }
                
            
        }
        
    }
    
    private void pausar(Object exp1)
    {
        NodoArbol time = evaluarExp((NodoArbol)exp1);
        int retardo = Integer.parseInt(time.getHojas().get(0).toString());
        try {
            Thread.sleep(retardo);
        } catch (InterruptedException ex) {
            Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private NodoArbol evaluarExp(NodoArbol exp)
    {
        NodoArbol inicio = exp;
        NodoArbol izq, der, val;
        val = null;
        int tipo = exp.getEtiqueta();
        
        switch(tipo)
        {
            case Instruccion.VALOR:
                int ide = (Integer)inicio.getHojas().get(1);
                
                if(ide == Tipo.ID)
                {
                    val = valorID(exp);
                    return val;
                }
                else
                {
                    return inicio;
                }
                
                
            case Instruccion.FUNCION:
                //return funcion
                val = evaluarFunciones(exp);
                break;
            case Instruccion.AND:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = comparacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.XOR:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = comparacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.OR:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = comparacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.MAYOR:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.MAYORIGUAL:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.MENOR:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.MENORIGUAL:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesLogicas(izq, der, tipo);
                }
                break;
                
            case Instruccion.IGUAL:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionIgualacion(izq, der, tipo);
                }
                break;
                
            case Instruccion.NOIGUAL:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionIgualacion(izq, der, tipo);
                }
                break;
                
            case Instruccion.NULO:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                
                
                if(izq!=null )
                {
                    //val
                }
                break;
                
            case Instruccion.POR:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesAritmeticas(izq, der, tipo);
                }
                break;
                
            case Instruccion.DIV:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesAritmeticas(izq, der, tipo);
                }
                break;
                
            case Instruccion.MAS:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesAritmeticas(izq, der, tipo);
                }
                break;
                
                
            case Instruccion.MENOS:
                
                izq = evaluarExp((NodoArbol)exp.getHojas().get(0));
                der = evaluarExp((NodoArbol)exp.getHojas().get(1));
                
                if(izq!=null && der!= null)
                {
                    val = operacionesAritmeticas(izq, der, tipo);
                }
                break;
                
                
                
                
                
        }
        
        
        
        
        return val;
        
    }
    
    private NodoArbol valorID(NodoArbol exp)
    {
        NodoArbol val = null;
        Simbolo sim;
        String ide = exp.getHojas().get(0).toString();
        sim = tabla.buscarSimbolo(ide);
        if(sim!=null)
        {
            if(sim.getValor()!=null)
            {
                val = new NodoArbol(Instruccion.VALOR);
                val.agregarHijo(sim.getValor());
                val.agregarHijo(sim.getTipo());
                return val;
                
            }
            
        }
        
        
        return val;
    }

    private NodoArbol operacionesAritmeticas(NodoArbol iz, NodoArbol de, int op)
    {
        NodoArbol val= null;
        int tde, tiz;
        float resultado;
               

        tiz = (Integer)iz.getHojas().get(1);
        tde = (Integer)de.getHojas().get(1);
        
        if(tiz == Tipo.LONG || tde == Tipo.LONG)
        {
            resultado = getResultadoAritmetico(iz.getHojas().get(0),de.getHojas().get(0), op);
            long casteo = (long)resultado;
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(casteo));
            val.agregarHijo(Tipo.LONG);
        }
        else if(tiz == Tipo.FLOAT || tde == Tipo.FLOAT)
        {
            resultado = getResultadoAritmetico(iz.getHojas().get(0),de.getHojas().get(0), op);
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(resultado));
            val.agregarHijo(Tipo.FLOAT);
        }
        else if(tiz == Tipo.ENTERO && tde == Tipo.ENTERO)
        {
            resultado = getResultadoAritmetico(iz.getHojas().get(0),de.getHojas().get(0), op);
            int casteo = (int)resultado;
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(casteo));
            val.agregarHijo(Tipo.ENTERO);
            
        }


        

        return val;
    }
    
    private float getResultadoAritmetico(Object e1, Object e2, int op)
    {
        float resultado = 0;
        float exp1 = Float.parseFloat(e1.toString());
        float exp2 = Float.parseFloat(e2.toString());
        
        switch(op)
        {
            case Instruccion.MAS:                
                resultado = exp1 + exp2;
                break;
            case Instruccion.MENOS:
                resultado = exp1 - exp2;
                break;
            case Instruccion.POR:
                resultado = exp1 * exp2;
                break;
            case Instruccion.DIV:
                resultado = exp1 / exp2;
                break;           
        }
        
        return resultado;
    }
    
    private NodoArbol operacionesLogicas(NodoArbol iz, NodoArbol de, int op)
    {
        NodoArbol val= null;
        int tde, tiz;
        boolean resultado;
               

        tiz = (Integer)iz.getHojas().get(1);
        tde = (Integer)de.getHojas().get(1);
        
        int res = validar.OpLogicos(tiz, tde);
        if(res!=-1)
        {
            resultado = getResultadoLogico(iz.getHojas().get(0),de.getHojas().get(0), op);            
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(resultado));
            val.agregarHijo(Tipo.BOOL);
        }


        

        return val;
    }
       
    private boolean getResultadoLogico(Object e1, Object e2, int op)
    {
        boolean resultado = false;
        float exp1 = Float.parseFloat(e1.toString());
        float exp2 = Float.parseFloat(e2.toString());
        
        switch(op)
        {
            case Instruccion.MENOR:                
                resultado = exp1 < exp2;
                break;
            case Instruccion.MENORIGUAL:
                resultado = exp1 <= exp2;
                break;
            case Instruccion.MAYOR:
                resultado = exp1 > exp2;
                break;
            case Instruccion.MAYORIGUAL:
                resultado = exp1 >= exp2;
                break;           
        }
        
        return resultado;
    }
    
    private NodoArbol comparacionesLogicas(NodoArbol iz, NodoArbol de, int op)
    {
        NodoArbol val = null;
        int tde, tiz;
        boolean resultado;
        tiz = (Integer)iz.getHojas().get(1);
        tde = (Integer)de.getHojas().get(1);
        
        if(tiz == Tipo.BOOL && tde == Tipo.BOOL)
        {
            resultado =  getResultadoComparacion(iz.getHojas().get(0),de.getHojas().get(0), op);
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(resultado));
            val.agregarHijo(Tipo.BOOL);
        }
        
        
        return val;
    }
    
    private boolean getResultadoComparacion(Object e1, Object e2, int op)
    {
        boolean resultado = false;
        boolean exp1 = Boolean.parseBoolean(e1.toString());
        boolean exp2 = Boolean.parseBoolean(e2.toString());
        
        switch(op)
        {
            case Instruccion.AND:                
                resultado = exp1 && exp2;
                break;
            case Instruccion.OR:
                resultado = exp1 || exp2;
                break;
            case Instruccion.XOR:
                resultado = exp1 == exp2;
                break;                      
        }
        
        return resultado;
    }
    
    private NodoArbol operacionIgualacion(NodoArbol iz, NodoArbol de, int op)
    {
        NodoArbol val= null;
        int tde, tiz;
        boolean resultado;
               

        tiz = (Integer)iz.getHojas().get(1);
        tde = (Integer)de.getHojas().get(1);
        
        int res = validar.OpIgulacion(tiz, tde);
        if(res!=-1)
        {
            resultado = getResultadoIgualacion(iz.getHojas().get(0),de.getHojas().get(0),tiz, op);            
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(resultado));
            val.agregarHijo(Tipo.BOOL);
        }


        

        return val;
    }
    
    private boolean getResultadoIgualacion(Object e1, Object e2, int tipo, int op)
    {
        boolean resultado = false;
        
        
        if(tipo == Tipo.ENTERO || tipo == Tipo.FLOAT || tipo == Tipo.LONG )
        {
            float exp1 = Float.parseFloat(e1.toString());
            float exp2 = Float.parseFloat(e2.toString());
            
            if(op == Instruccion.IGUAL)
            {
                resultado = exp1 == exp2;
                return resultado;
            }
            else if(op == Instruccion.NOIGUAL)
            {
                resultado = exp1 != exp2;
                return resultado;
            }
        }
        else if(tipo == Tipo.STRING)
        {
            String exp1 = e1.toString();
            String exp2 = e2.toString();
            
            if(op == Instruccion.IGUAL)
            {
                resultado = exp1.compareTo(exp2)==0;
                return resultado;
            }
            else if(op == Instruccion.NOIGUAL)
            {
                resultado = exp1.compareTo(exp2)!=0;
                return resultado;
            }
            
        }
        else if(tipo == Tipo.BOOL)
        {
            boolean exp1 = Boolean.parseBoolean(e1.toString());
            boolean exp2 = Boolean.parseBoolean(e2.toString());
            
            if(op == Instruccion.IGUAL)
            {
                resultado = exp1==exp2;
                return resultado;
            }
            else if(op == Instruccion.NOIGUAL)
            {
                resultado = exp1!=exp2;
                return resultado;
            }
            
        }
        else if(tipo == Tipo.CHAR)
        {
            char exp1 = e1.toString().charAt(0);
            char exp2 = e2.toString().charAt(0);
            
            if(op == Instruccion.IGUAL)
            {
               resultado = exp1==exp2;
                return resultado;
            }
            else if(op == Instruccion.NOIGUAL)
            {
                resultado = exp1!=exp2;
                return resultado;
            }
            
        }
        
        return resultado;
    }
    
    private NodoArbol getMnuniciones(NodoArbol exp)
    {
        NodoArbol val= null;
        NodoArbol idenemigo = evaluarExp((NodoArbol)exp.getHojas().get(0));
        int valorenemigo = Integer.parseInt(idenemigo.getHojas().get(0).toString());
        
        NodoEnemigo enemigo = buscarEnemigo(valorenemigo);
        
        if(enemigo!=null)
        {
            int muni = buscarMuncionesEnemigo(valorenemigo);
            val = new NodoArbol(Instruccion.VALOR);
            val.agregarHijo(String.valueOf(muni));
            val.agregarHijo(Tipo.ENTERO);
            return val;
        }


        
        return val;
    }
    
    private NodoArbol getLibre(NodoArbol exp)
    {
        int w = casillas.length;
        int h = casillas[casillas.length-1].length;
        
        NodoArbol val = null;
        NodoArbol enemigo = evaluarExp((NodoArbol)exp.getHojas().get(0));
        NodoArbol posx = evaluarExp((NodoArbol)exp.getHojas().get(1));
        NodoArbol posy = evaluarExp((NodoArbol)exp.getHojas().get(2));
        int venemigo = Integer.parseInt(enemigo.getHojas().get(0).toString());
        int px = Integer.parseInt(posx.getHojas().get(0).toString());
        int py = Integer.parseInt(posy.getHojas().get(0).toString());
        
        
        if((px >= 0 && px < w)&& (py >= 0 && py < h ))
        {
            val = new NodoArbol(Instruccion.VALOR);

            if(casillas[px][py].getEspacio().isPasable())
            {
                if (px != jugx && py != jugy) {

                       val.agregarHijo("true");
                       val.agregarHijo(Tipo.BOOL);
                }                
                else
                {
                    Enemigo enemy = buscarEnemigo2(venemigo);
                    
                    if(enemy!=null)
                    {
                        String bool = "true"; 
                        for(Enemigo enemi: lstenemigos)
                        {
                            if(enemi!=enemy)
                            {
                                if(enemi.getCol() == px && enemi.getFil() == py)
                                {
                                    bool = "false";
                                    break;                                            
                                }
                            }
                        }
                        
                        val.agregarHijo(bool);
                        val.agregarHijo(Tipo.BOOL);
                    }
                    else
                    {
                        val.agregarHijo("false");
                        val.agregarHijo(Tipo.BOOL);
                    }

                    
                }

            }
            else
            {
                val.agregarHijo("false");
                val.agregarHijo(Tipo.BOOL);
            }            
            return val;
        }
        else
        {
             val = new NodoArbol(Instruccion.VALOR);
             val.agregarHijo("false");
             val.agregarHijo(Tipo.BOOL);

        }
        
        
        return val;
    }
    
    
    
    private NodoArbol bordeTab(NodoArbol exp)
    {
        NodoArbol val = null;
        NodoArbol enemigo = evaluarExp((NodoArbol)exp.getHojas().get(0));
        int idenemigo = Integer.parseInt(enemigo.getHojas().get(0).toString());
        
        Enemigo enemy = buscarEnemigo2(idenemigo);
        
        if(enemy!=null)
        {
            int w = casillas.length;
            int h = casillas[casillas.length-1].length;
            val = new NodoArbol(Instruccion.VALOR);
            if(enemy.getCol() == 0 || enemy.getCol()== w-1 || enemy.getFil()==0 || enemy.getFil()== h-1)
            {
                val.agregarHijo("true");
                val.agregarHijo(Tipo.BOOL);
            }
            else
            {
                val.agregarHijo("false");
                val.agregarHijo(Tipo.BOOL);
            }
            
            return val;
            
        }
        
        return val;
    }
    
    private NodoArbol getVal(NodoArbol exp)
    {
        NodoArbol val = null;
        NodoArbol variable = (NodoArbol)exp.getHojas().get(0);
        String ide= String.valueOf(variable.getHojas().get(0));
        Simbolo sim = tabla.buscarSimbolo(ide);
        
        if(sim != null)
        {
            
            
            if(sim.getValor()!=null)
            {
                val = new NodoArbol(Instruccion.VALOR);
                val.agregarHijo(sim.getValor());
                val.agregarHijo(sim.tipo);
                return val;
            }
            
        }
        
        
        
        
        return val;
        
    }
    
    private NodoArbol getF(NodoArbol exp)
    {
        NodoArbol val = null;
        NodoArbol expr = (NodoArbol)exp.getHojas().get(0);
        int tipo = (Integer)expr.getHojas().get(1);
        
        if(tipo==Tipo.ID)
        {
            
            String ide= String.valueOf(expr.getHojas().get(0));
            Simbolo sim = tabla.buscarSimbolo(ide);

            if(sim != null)
            {


                if(sim.getValor()!=null)
                {
                    val = new NodoArbol(Instruccion.VALOR);
                    val.agregarHijo(sim.getValor());
                    val.agregarHijo(Tipo.STRING);
                    return val;
                }

            } 
        }
        

        
        return val;
        
    }
    
    private NodoArbol getStr(NodoArbol exp) {
        
        NodoArbol val = null;
        NodoArbol expr = evaluarExp((NodoArbol)exp.getHojas().get(0));
        
        if(expr!=null)
        {
            if(expr.getEtiqueta()== Instruccion.VALOR)
            {
                val = new NodoArbol(expr.getEtiqueta());
                val.agregarHijo(expr.getHojas().get(0));
                val.agregarHijo(Tipo.STRING);
            }
            
        }
        
       
        
        return val;
        
    }
    
    private NodoArbol getBool(NodoArbol exp)
    {
        NodoArbol val = null;
        NodoArbol expr = evaluarExp((NodoArbol)exp.getHojas().get(0));
        
        if(expr!=null)
        {
            if(expr.getEtiqueta()== Instruccion.VALOR)
            {
                boolean valor = Boolean.parseBoolean(expr.getHojas().get(0).toString());
                
                val = new NodoArbol(Instruccion.VALOR);
                val.agregarHijo(String.valueOf(valor));
                val.agregarHijo(Tipo.BOOL);
            }
            
        }
        
       
        
        return val;
    }
    
    private NodoArbol getInt(NodoArbol exp)
    {
        NodoArbol val = null;
        NodoArbol expr = evaluarExp((NodoArbol)exp.getHojas().get(0));
        
        if(expr!=null)
        {
            if(expr.getEtiqueta()== Instruccion.VALOR)
            {
                int tipo = (Integer)expr.getHojas().get(1);
                
                if(tipo == Tipo.BOOL)
                {
                    boolean valor = Boolean.parseBoolean(expr.getHojas().get(0).toString());
                    int intvalor = valor?1:0;
                    val = new NodoArbol(Instruccion.VALOR);
                    val.agregarHijo(String.valueOf(intvalor));
                    val.agregarHijo(Tipo.ENTERO);
                    return val;
                    
                }
                else if(tipo == Tipo.FLOAT)
                {
                    float valor = Float.parseFloat(expr.getHojas().get(0).toString());
                    int intvalor = (int)valor;
                    val = new NodoArbol(Instruccion.VALOR);
                    val.agregarHijo(String.valueOf(intvalor));
                    val.agregarHijo(Tipo.ENTERO);
                    return val;
                    
                }
                else if(tipo == Tipo.CHAR)
                {
                    char valor = expr.getHojas().get(0).toString().charAt(0);
                    int intvalor = (int)valor;
                    val = new NodoArbol(Instruccion.VALOR);
                    val.agregarHijo(String.valueOf(intvalor));
                    val.agregarHijo(Tipo.ENTERO);
                    return val;
                    
                }
                else 
                {
                    int valor;
                    try{
                        valor = Integer.parseInt(expr.getHojas().get(0).toString());
                        
                    }catch(NumberFormatException ex)
                    {
                        valor = 0;
                        //marcar error
                    }
                    
                    val = new NodoArbol(Instruccion.VALOR);
                    val.agregarHijo(String.valueOf(valor));
                    val.agregarHijo(Tipo.ENTERO);
                    
                    
                }
               
                
                
            }
            
        }
        
       
        
        return val;
    }
    
    private NodoArbol armaPropia(NodoArbol exp)
    {
        NodoArbol val= null;
        
        NodoArbol idenemigo = evaluarExp((NodoArbol)exp.getHojas().get(0));
        NodoArbol idarma = evaluarExp((NodoArbol)exp.getHojas().get(1));
        int tipoenemigo = Integer.parseInt(idenemigo.getHojas().get(1).toString());
        int tipoarma = Integer.parseInt(idarma.getHojas().get(1).toString());
        
        if(tipoenemigo == Tipo.ENTERO && tipoarma == Tipo.ENTERO)
        {
            int valorenemigo = Integer.parseInt(idenemigo.getHojas().get(0).toString());
            int valorarma = Integer.parseInt(idarma.getHojas().get(0).toString());
            
            if(existeEnemigo(valorenemigo) && existeArma(valorarma))
            {
               if(buscarArmaEnemigo(valorenemigo, valorarma)!=null)
               {
                   val = new NodoArbol(Instruccion.VALOR);
                   val.agregarHijo("true");
                   val.agregarHijo(Tipo.BOOL);
                   return val;
               }
               else
               {
                   val = new NodoArbol(Instruccion.VALOR);
                   val.agregarHijo("false");
                   val.agregarHijo(Tipo.BOOL);
                   return val;
                   
               }
            }
        }
        
        
        return val;
    }
    
    private NodoArbol incrementarID(NodoArbol exp, int op)
    {
        NodoArbol val = null;
        NodoArbol expr = (NodoArbol)exp.getHojas().get(0);
        int tipo = (Integer)expr.getHojas().get(1);
        
        if(tipo==Tipo.ID)
        {
            
            String ide= String.valueOf(expr.getHojas().get(0));
            Simbolo sim = tabla.buscarSimbolo(ide);

            if(sim != null)
            {                
                if(sim.getValor()!=null && sim.getTipo()==Tipo.ENTERO)
                {
                    String valor = sim.getValor().toString();
                    int intvalor = Integer.parseInt(valor);
                    int res  =0;
                    
                    if(op == Instruccion.AUMENTAR)
                    {
                        res = intvalor + 1;
                    }
                    else if(op == Instruccion.DISMINUIR)
                    {
                        res = intvalor - 1;
                    }
                        
                    valor = String.valueOf(res);
                    sim.setValor(valor);
                    val = new NodoArbol(Instruccion.VALOR);
                    val.agregarHijo(valor);
                    val.agregarHijo(Tipo.ENTERO);
                    return val;
                }

            } 
            
        }
        return val;
    }
    
    private NodoArbol evaluarFunciones(NodoArbol exp)
    {
        NodoArbol val= null;        
        NodoArbol funcion = (NodoArbol)exp.getHojas().get(0);
        int tipofuncion = funcion.getEtiqueta();
        
        switch(tipofuncion)
        {
            case Instruccion.GETMUNI:
                val = getMnuniciones(funcion);
                break;
            case Instruccion.GETLIBRE:
                val = getLibre(funcion);
                break;
            case Instruccion.BORDETAB:
                val = bordeTab(funcion);
                break;
            case Instruccion.GETVAL:
                val = getVal(funcion);
                break;
                
            case Instruccion.GETF:
                val = getF(funcion);
                break;
            case Instruccion.GETSTR:
                val = getStr(funcion);
                break;
            case Instruccion.GETBOOL:
                val = getBool(funcion);
                break;
            case Instruccion.GETINT:
                val = getInt(funcion);
                break;
            case Instruccion.AUMENTAR:
                val = incrementarID(funcion, Instruccion.AUMENTAR);
                break;
            case Instruccion.DISMINUIR:
                val = incrementarID(funcion, Instruccion.DISMINUIR);
                break;
            case Instruccion.ARMAPROPIA:
                val = armaPropia(funcion);
        }
        
        return val;
    }
    
    private int analizarCondicion(NodoArbol exp)
     {
         
         NodoArbol condicion;
         int tipo;
         int valida =-1;
         boolean cond;
         
         
         condicion = evaluarExp(exp);
         
         if(condicion!=null)
         {
             tipo = Integer.parseInt(condicion.getHojas().get(1).toString());
             
             if(tipo==Tipo.BOOL)
             {
                 String aux = condicion.getHojas().get(0).toString();
                 
                 cond = Boolean.parseBoolean(aux);
                 
                 if(cond)
                 {
                     valida = 1;
                 }
                 else
                 {
                     valida = 0;
                 }
             }
         }
         
         return valida;
         
     }  
    
    private void analizarWhile(ArrayList<Object> mientras)
     {
         NodoArbol condicion, cuerpo; 
          ArrayList<Object> sentencias;
         int cond;
         detener = false;
         condicion = (NodoArbol)mientras.get(0);
         
         cond = analizarCondicion(condicion);
         sentencias = (ArrayList<Object>)mientras.get(1);
         
         while(cond==1)
         {
             EjecutarInstrucciones(sentencias);
             if(detener)
             {
                 break;
             }
             cond = analizarCondicion(condicion);
             
             try {
                 Thread.sleep(400);
             } catch (InterruptedException ex) {
                 Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
             }
             
         }
     }
    
    private void analizarIf(ArrayList<Object> sentif)
     {
         NodoArbol condicion, nodoif, nodoelses;
         NodoArbol nodotemp;
         ArrayList<Object> listaelses;
         int cond;
         
         if(sentif.size()<2)//if sin else ni elses if
         {
             nodoif = (NodoArbol)sentif.get(0);
             condicion = (NodoArbol)nodoif.getHojas().get(0);
             
             cond = analizarCondicion(condicion);
             
             if(cond==1)
             {
                 EjecutarInstrucciones((ArrayList<Object>)nodoif.getHojas().get(1));
                 
             }
         }
         else// if con else o else if o ambos
         {
             nodoif = (NodoArbol)sentif.get(0);
             condicion = (NodoArbol)nodoif.getHojas().get(0);
             
             cond = analizarCondicion(condicion);
             
             if(cond==1)
             {
                 EjecutarInstrucciones((ArrayList<Object>)nodoif.getHojas().get(1));
             }
             else
             {
                 nodoelses = (NodoArbol)sentif.get(1);
                 
                 if(nodoelses.getEtiqueta()==Instruccion.ELSE)//solo con else
                 {
              
                     EjecutarInstrucciones((ArrayList<Object>)nodoelses.getHojas().get(0));
                 }
                 else if(nodoelses.getEtiqueta()== Instruccion.ELSEIFS)
                 {
                     listaelses = (ArrayList<Object>)nodoelses.getHojas().get(0);
                   
                     for(Object auxelses: listaelses)
                     {
                         nodoif = (NodoArbol)auxelses;
                         condicion = (NodoArbol)nodoif.getHojas().get(0);
                         cond = analizarCondicion(condicion);
                         
                         if(cond==1)
                         {
                             EjecutarInstrucciones((ArrayList<Object>)nodoif.getHojas().get(1));
                             return;
                         }
                     }
                    
                 }
                 else if(nodoelses.getEtiqueta()==Instruccion.ELSEIF_ELSE)
                 {
                     listaelses = (ArrayList<Object>)nodoelses.getHojas().get(0);
                     
                     for(Object auxelses: listaelses)
                     {
                         nodoif = (NodoArbol)auxelses;
                         condicion = (NodoArbol)nodoif.getHojas().get(0);
                         cond = analizarCondicion(condicion);
                         
                         if(cond==1)
                         {
                             EjecutarInstrucciones((ArrayList<Object>)nodoif.getHojas().get(1));
                             return;
                         }
                     }
                     
                     nodotemp = (NodoArbol)nodoelses.getHojas().get(1);
                     
                     EjecutarInstrucciones((ArrayList<Object>)nodotemp.getHojas().get(0));
                     
                     
                 }
//                 
             }
         }
     }
    
    private void analizarFor(ArrayList<Object> repetir)
     {
         NodoArbol inicio,salto;
         NodoArbol valor1, valor2, exp1;
         ArrayList<Object> sentencias;
         int cond, tipo;
         Token var1;
         var1 = (Token)repetir.get(0);
         valor1 = (NodoArbol)repetir.get(1);
         tipo = (Integer)repetir.get(2);
         valor2 = (NodoArbol)repetir.get(4);
         sentencias = (ArrayList<Object>)repetir.get(5);
         detener =false;
         ejecutarSetf(var1, valor1); //inicializamos la variable
         
         inicio = new NodoArbol(Instruccion.NOIGUAL); //creamo los valores para la comparacion
         exp1 = new NodoArbol(Instruccion.VALOR);
         exp1.agregarHijo(var1.getLexema());
         exp1.agregarHijo(Tipo.ID);
         
         inicio.agregarHijo(exp1);
         inicio.agregarHijo(valor2);
         
         salto = new NodoArbol(tipo); //aumento o disminur
         salto.agregarHijo(exp1);
         
         cond = analizarCondicion(inicio);
         
         while(cond==1)
         {
             
             
             
             EjecutarInstrucciones(sentencias);
             if(detener)
             {
                 break;
             }
             
             incrementarID(salto, tipo);             
             cond = analizarCondicion(inicio);
             try {
                 Thread.sleep(400);
             } catch (InterruptedException ex) {
                 Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
             }
             
         }
          
         
     }
    
    @Override
    protected void finalize() throws Throwable {
       
        hilo.stop();
        super.finalize();
    }
    
    @Override
    public void run()
    {
        EjecutarEstrategia();
        
    }
    
    private void MoverEnemigos(Coordenada coordenada)
    {
        
            
                int delay = 200;
                Coordenada coor= movimiento(coordenada);
                
                 int vel = 10;
                 int dir = coor.getDir();

                 int xf = tablero.casillas[coor.getFil()][coor.getCol()].getX() + (tablero.casillas[coor.getFil()][coor.getCol()].getAncho() / 2 - coor.getEnemigo().getAncho() / 2);
                 int yf = tablero.casillas[coor.getFil()][coor.getCol()].getY() + (tablero.casillas[coor.getFil()][coor.getCol()].getAlto() / 2 - coor.getEnemigo().getAlto() / 2);
                 Enemigo enemi = coor.getEnemigo();

                 switch (dir) {
                     case 1:
                         while(coor.getEnemigo().getY() > yf)
                         {
                            try {
                                coor.getEnemigo().setY(coor.getEnemigo().getY() - vel);
                                Thread.sleep(delay);
                                
                            } catch (InterruptedException ex) {
                                Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                            }
                         }
                         
                         if (coor.getEnemigo().getY() <= yf) {
                             coor.getEnemigo().setY(yf);
                             coor.getEnemigo().setX(xf);
                             coor.getEnemigo().setCol(coor.getCol());
                             coor.getEnemigo().setFil(coor.getFil());
                             coor.setCompleta(true);
                            
                         }
                         break;
                     case 2:
                         
                         while(coor.getEnemigo().getX() < xf)
                         {
                            try {
                                coor.getEnemigo().setX(coor.getEnemigo().getX() + vel);
                                Thread.sleep(delay);
                                
                            } catch (InterruptedException ex) {
                                Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                            }
                         }
                         
                        
                         if (coor.getEnemigo().getX() >= xf) {
                             coor.getEnemigo().setX(xf);
                             coor.getEnemigo().setY(yf);
                             coor.getEnemigo().setCol(coor.getCol());
                             coor.getEnemigo().setFil(coor.getFil());
                             coor.setCompleta(true);
                             
                         }
                         break;

                     case 3:
                         
                         while(coor.getEnemigo().getY() < yf)
                         {
                            try {
                                coor.getEnemigo().setY(coor.getEnemigo().getY() + vel);
                                Thread.sleep(delay);
                                
                            } catch (InterruptedException ex) {
                                Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                            }
                         }
                         
                         if (coor.getEnemigo().getY() >= yf) {
                             coor.getEnemigo().setY(yf);
                             coor.getEnemigo().setX(xf);
                             coor.getEnemigo().setCol(coor.getCol());
                             coor.getEnemigo().setFil(coor.getFil());
                             coor.setCompleta(true);
                             
                         }
                         break;
                     case 4:
                         
                         
                         while((coor.getEnemigo().getX() > xf))
                         {
                            try {
                                coor.getEnemigo().setX(coor.getEnemigo().getX() - vel);
                                Thread.sleep(delay);
                                
                            } catch (InterruptedException ex) {
                                Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                            }
                         }
                         
                         if (coor.getEnemigo().getX() <= xf) {
                             coor.getEnemigo().setX(xf);
                             coor.getEnemigo().setY(yf);
                             coor.getEnemigo().setCol(coor.getCol());
                             coor.getEnemigo().setFil(coor.getFil());
                             coor.setCompleta(true);
                             
                         }
                         break;

                 }
             
        
    }
    
    private Coordenada movimiento(Coordenada cor)
    {
        int h = tablero.getNivel().getAlto();
        int w = tablero.getNivel().getAncho();
        int dir = cor.getDir();
        int actual;
        int fin;
        switch(dir)
        {
            case 1: //arriba
                
                if(cor.getFil() <= 0)
                {
                    cor.setFil(0);
                }
                
                actual = cor.getEnemigo().getFil();
                fin = cor.getFil();

                for(int c = actual-1 ; c>=fin; c--)
                {
                    if(!tablero.casillas[c][cor.getCol()].getEspacio().isPasable())
                    {
                        break;
                    }
                    actual--;
                }

                cor.setFil(actual);
                
                break;
                
            case 2: //derecha
                
                if(cor.getCol()>= w-1)
                {
                    cor.setCol(w-1);
                }
                actual = cor.getEnemigo().getCol();
                fin = cor.getCol();

                for(int c = actual+1 ; c<=fin; c++)
                {
                    if(!tablero.casillas[cor.getFil()][c].getEspacio().isPasable())
                    {
                        break;
                    }
                    actual++;
                }

                cor.setCol(actual);
                
                break;
           case 3: //abajo
                
                if(cor.getFil() >= h-1)
                {
                    cor.setFil(h-1);
                }
                
                actual = cor.getEnemigo().getFil();
                fin = cor.getFil();

                for(int c = actual+1 ; c<=fin; c++)
                {
                    if(!tablero.casillas[c][cor.getCol()].getEspacio().isPasable())
                    {
                        break;
                    }
                    actual++;
                }

                cor.setFil(actual);
                
                break;
                
            case 4: //izquierda
                
                if(cor.getCol()<= 0)
                {
                    cor.setCol(0);
                }
                
                actual = cor.getEnemigo().getCol();
                fin = cor.getCol();

                for(int c = actual-1 ; c>=fin; c--)
                {
                    if(!tablero.casillas[cor.getFil()][c].getEspacio().isPasable())
                    {
                        break;
                    }
                    actual--;
                }

                cor.setCol(actual);
                
                break;
        }
        
        return cor;
        
    }

    private void moverDisparo(Ataque a)
    {
        int VEL =20;
        switch(a.getDir())
            {
                case 1:  //  direccion hacia arriba
                    
                    while(a.getY()>a.getLimitey1()&&a.isVisible())
                    {
                       a.setY(a.getY()-VEL);
                       colisionDisparoParedes(a);
                       disparoEnemigosJugador();
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    }
                    

                    if(a.getY()<a.getLimitey1())
                    {
                        a.setVisible(false);
                        a.setY(a.getLimitey1());
                        a.getEstrategia().actualizarpunteo(-2);
                    }

                    break;

                case 2: // direccion hacia la derecha                    

                    while(a.getX()<a.getLimitex2()&&a.isVisible())
                    {
                       a.setX(a.getX()+VEL);
                       colisionDisparoParedes(a);
                       disparoEnemigosJugador();
                       try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    }

                    if(a.getX()>a.getLimitex2())
                    {
                        a.setVisible(false);
                        a.setX(a.getLimitex2());
                        a.getEstrategia().actualizarpunteo(-2);
                    }

                    
                    break;

                case 3: // direccion hacia abajo

                    while(a.getY()<a.getLimitey2()&&a.isVisible())
                    {
                       a.setY(a.getY()+VEL);
                       colisionDisparoParedes(a);
                       disparoEnemigosJugador();
                       try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    }


                    if(a.getY()>a.getLimitey2())
                    {
                        a.setVisible(false);
                        a.setY(a.getLimitey2());
                        a.getEstrategia().actualizarpunteo(-2);
                    }
                    
                    
                    break;

                case 4: // direccion hacia la izquierda

                    while(a.getX()>a.getLimitex1()&&a.isVisible())
                    {
                       a.setX(a.getX()-VEL);
                       colisionDisparoParedes(a);
                       disparoEnemigosJugador();
                       try {
                            Thread.sleep(100);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Ejecucion.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    }

                    if(a.getX()<a.getLimitex1())
                    {
                        a.setVisible(false);
                        a.setX(a.getLimitex1());
                        a.getEstrategia().actualizarpunteo(-2);
                    }
                    
                    
                    break;

                default:
                    System.out.println("direccion no valida");

            }
    }

    private void colisionDisparoParedes(Ataque magia)
    {
        int w = casillas.length;
        int h = casillas[w-1].length;
        Casilla aux;
        Rectangle u1, u2;

        for(int f=0;f<w;f++ )
        {
            for (int c= 0; c < h; c++) {

                aux = casillas[f][c];
                u2 = aux.getLimite();



                

                    u1 = magia.getUbicacion();

                    if(u1.intersects(u2))
                    {
                        if(!casillas[f][c].getEspacio().isPasable())
                        {
                            if(magia.getEstrategia()!=null)
                            {
                                magia.getEstrategia().actualizarpunteo(-2);
                            }
                            magia.setVisible(false);
                            System.out.println("desaparece");

                        }

                    }
                    else
                    {
                          System.out.println("no paso nada en la colision");
                    }
                


            }
        }
    }

    private void disparoEnemigosJugador()//metodo que realiza el ataque hacia a el jugador
    {
        ArrayList<Ataque> ataques;
        Rectangle u1, u2;
        int coli =0;
        for (Enemigo enemigo: tablero.getEnemigos()) {

            ataques = enemigo.getDisparos();
            coli =0;
            for(Ataque a: ataques)
            {
                u1 = tablero.getJugador().getUbicacion();
                u2 = a.getUbicacion();

                if(u1.intersects(u2))
                {
                    NodoEstrategia es = a.getEstrategia();
                    if(es!=null)
                    {
                        int pot = a.getPotencia();
                        int resultado = 0;
                        switch(pot)
                        {
                            case NivelPotencia.TINNY:
                                resultado = (int)(tablero.getJugador().getVida() * 0.05);
                                break;
                            case NivelPotencia.LOW:
                                resultado = (int)(tablero.getJugador().getVida() * 0.10);
                                break;
                            case NivelPotencia.MEDIUM:
                                resultado = (int)(tablero.getJugador().getVida() * 0.20);
                                break;
                            case NivelPotencia.HIGHT:
                                resultado = (int)(tablero.getJugador().getVida() * 0.50);
                                break;
                            case NivelPotencia.HEAVY:
                                resultado = (int)(tablero.getJugador().getVida() * 1);
                                break;
                        }

                        tablero.getJugador().restarVida(resultado);
                        es.actualizarpunteo(10);
                        coli++;
                        tablero.verificarVidaJugador();
                        a.setVisible(false);
                    }
                }
                else
                {
                    for(Enemigo enemigo2: tablero.getEnemigos())
                    {
                        if(enemigo!= enemigo2)
                        {
                            u1 = enemigo2.getUbicacion();

                            if(u1.intersects(u2))
                            {
                                NodoEstrategia es = a.getEstrategia();
                                if(es!=null)
                                {


                                    es.actualizarpunteo(-5);

                                    a.setVisible(false);
                                    coli++;
                                }
                            }
                        }
                    }
                }

//                if(coli==0)
//                {
//                    if(a.getEstrategia()!=null)
//                    {
//                        a.getEstrategia().actualizarpunteo(-2);
//                    }
//                }
            }


        }
    }

    private void disparar(Enemigo en)
    {
        Ataque a;
        for(int i= 0; i< en.getDisparos().size();)
        {
            a = en.getDisparos().get(i);
            if(a.isVisible())
            {
                moverDisparo(a);
            }
            else
            {
//                en.getDisparos().remove(i);
                i++;
            }
        }
    }

}
